package com.emperor.report.app;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;

import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.hibernate.Session;
import org.hibernate.criterion.Expression;
import org.hibernate.criterion.Order;

import com.emperor.cashier.app.CashierAppCtrl;
import com.emperor.category.logic.Category;
import com.emperor.category.logic.CategoryModel;
import com.emperor.core.app.App;
import com.emperor.core.app.AppBase;
import com.emperor.core.app.AppConstant;
import com.emperor.employee.app.EmployeeAppCtrl;
import com.emperor.employee.logic.Employee;
import com.emperor.employee.logic.EmployeeModel;
import com.emperor.product.logic.Product;
import com.emperor.product.logic.ProductModel;
import com.emperor.util.DateFormatter;
import com.emperor.util.HibernateUtil;
import com.emperor.util.ReportUtil;
import com.swtdesigner.SWTResourceManager;

public class ReportAppEnq extends AppBase implements App {

	private Combo combo_3;
	private Combo combo_2;
	private Combo combo;
	protected Shell shell;
	public static Logger log = Logger.getLogger(ReportAppEnq.class);
	protected SimpleDateFormat sdf = new SimpleDateFormat(
			DateFormatter.YYYYMMDD);
	protected Category category;

	public ReportAppEnq() {
		super();
	}

	public ReportAppEnq(Map<String, Object> params) {
		super();
		this.params = params;
	}

	/**
	 * Launch the application
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			ReportAppEnq window = new ReportAppEnq();
			window.open();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Open the window
	 */
	public void open() {
		final Display display = Display.getDefault();
		createContents();
		shell.open();
		shell.layout();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
	}

	/**
	 * Create contents of the window
	 */
	protected void createContents() {
		shell = new Shell();
		shell.setBackgroundImage(SWTResourceManager.getImage(
				ReportAppEnq.class, "/img/main.jpg"));
		shell.setImage(SWTResourceManager.getImage(ReportAppEnq.class,
				"/img/iMac OSX.png"));
		shell.setFont(SWTResourceManager.getFont("", 12, SWT.NONE));
		shell.setBackgroundMode(SWT.INHERIT_DEFAULT);
		shell.setSize(1280, 800);
		shell.setText("Search Report");

		initScreen(shell, getParams());

		final Composite composite = new Composite(shell, SWT.NONE);
		composite.setBounds(0, 50, 972, 412);

		combo = new Combo(composite, SWT.READ_ONLY);
		combo.select(0);
		combo.setVisible(false);
		combo.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		combo.setBounds(115, 220, 521, 28);

		final Label startDateLabel_1 = new Label(composite, SWT.NONE);
		startDateLabel_1.setVisible(false);
		startDateLabel_1.setBounds(10, 223, 75, 20);
		startDateLabel_1.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		startDateLabel_1.setText("Category");

		combo_2 = new Combo(composite, SWT.READ_ONLY);
		combo_2.select(0);
		combo_2.setVisibleItemCount(20);
		combo_2.setBounds(115, 254, 521, 28);
		combo_2.setVisible(false);
		combo_2.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));

		final Label startDateLabel_1_1 = new Label(composite, SWT.NONE);
		startDateLabel_1_1.setBounds(10, 257, 75, 20);
		startDateLabel_1_1.setVisible(false);
		startDateLabel_1_1
				.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		startDateLabel_1_1.setText("Product");

		combo_3 = new Combo(composite, SWT.READ_ONLY);
		combo_3.select(0);
		combo_3.setBounds(115, 288, 521, 28);
		combo_3.setVisible(false);
		combo_3.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));

		final Label startDateLabel_1_2 = new Label(composite, SWT.NONE);
		startDateLabel_1_2.setBounds(10, 291, 75, 20);
		startDateLabel_1_2.setVisible(false);
		startDateLabel_1_2
				.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		startDateLabel_1_2.setText("Employee");

		final List list = new List(composite, SWT.V_SCROLL | SWT.BORDER);
		list.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				doShowForm(list, combo, combo_2, combo_3, startDateLabel_1,
						startDateLabel_1_1, startDateLabel_1_2);
			}
		});
		list.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		list.setBounds(10, 28, 626, 189);

		final Label startDateLabel = new Label(composite, SWT.NONE);
		startDateLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		startDateLabel.setText("Start Date");
		startDateLabel.setBounds(10, 326, 75, 20);

		final Label endDateLabel = new Label(composite, SWT.NONE);
		endDateLabel.setBounds(10, 358, 75, 20);
		endDateLabel.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		endDateLabel.setText("End Date");

		final Text startDateText = new Text(composite, SWT.BORDER);
		startDateText.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		startDateText.setBounds(115, 323, 210, 30);

		final Text endDateText = new Text(composite, SWT.BORDER);
		endDateText.setBounds(115, 358, 210, 30);
		endDateText.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));

		final Button button = new Button(composite, SWT.NONE);
		button.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				pickDate(getShell(), startDateText);
			}
		});
		button.setImage(SWTResourceManager.getImage(ReportAppEnq.class,
				"/img/Calendar.png"));
		button.setBounds(331, 322, 30, 30);

		final Button button_1 = new Button(composite, SWT.NONE);
		button_1.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				pickDate(getShell(), endDateText);
			}
		});
		button_1.setImage(SWTResourceManager.getImage(ReportAppEnq.class,
				"/img/Calendar.png"));
		button_1.setBounds(331, 358, 30, 30);

		final Button reportButton = new Button(shell, SWT.NONE);
		reportButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				displayReport(list, startDateText, endDateText, combo);
			}
		});
		reportButton.setImage(SWTResourceManager.getImage(ReportAppEnq.class,
				"/img/Printer.png"));
		reportButton.setFont(org.eclipse.wb.swt.SWTResourceManager.getFont("Segoe UI", 12, SWT.NORMAL));
		reportButton.setText("Report");
		reportButton.setBounds(115, 468, 85, 30);

		//
		buildStandardMenu(getShell(), getParams(), CashierAppCtrl.CASHIER_CTRL,
				CashierAppCtrl.CASHIER_FORM);
		populateList(list);
	}

	private void populateList(List list) {
		try {
			list.add("Sales Report");
			list.add("Inventory Report");
			list.add("Inventory Updates");
			list.add("Inventory Stock Card");
			list.add("Worksheet Report");
			list.add("Profit Report");
			list.add("Deleted Receipt Report");
		} catch (Exception e) {
			log.error("Unable to populate report list.", e);
		}
	}

	private void displayReport(List list, Text startText, Text endText,
			Combo combo) {
		try {
			Map params = new HashMap();
			if (startText.getText().length() > 0
					&& endText.getText().length() > 0) {
				Date startDate = sdf.parse(startText.getText());
				Calendar startCal = Calendar.getInstance();
				startCal.setTime(startDate);
				startCal.set(Calendar.HOUR, 12);
				startCal.set(Calendar.MINUTE, 0);
				startCal.set(Calendar.SECOND, 0);
				startCal.set(Calendar.AM_PM, Calendar.AM);

				params.put("start_date", startCal.getTime());

				Date endDate = sdf.parse(endText.getText());
				startCal.setTime(endDate);
				startCal.set(Calendar.HOUR, 12);
				startCal.set(Calendar.MINUTE, 0);
				startCal.set(Calendar.SECOND, 0);
				startCal.set(Calendar.AM_PM, Calendar.PM);

				params.put("end_date", startCal.getTime());
			} else {
				Calendar startCal = Calendar.getInstance();
				startCal.set(Calendar.HOUR, 12);
				startCal.set(Calendar.MINUTE, 0);
				startCal.set(Calendar.SECOND, 0);
				startCal.set(Calendar.AM_PM, Calendar.AM);

				params.put("start_date", startCal.getTime());

				startCal.set(Calendar.HOUR, 12);
				startCal.set(Calendar.MINUTE, 0);
				startCal.set(Calendar.SECOND, 0);
				startCal.set(Calendar.AM_PM, Calendar.PM);

				params.put("end_date", startCal.getTime());
			}

			if (list.getSelection() != null && list.getSelection().length > 0) {
				String[] selections = list.getSelection();
				for (int i = 0; i < selections.length; i++) {
					if (selections[i].equals("Sales Report")) {
						if (!StringUtils.isEmpty(combo_3.getText())) {
							String employeeName = combo_3.getText();
							if ("All Employees".equals(employeeName)) {
								ReportUtil.report("./report/All-Sales-Report.jrxml",
										params);
							} else {
								params.put(Employee.FLD_NAME, employeeName);
								
								ReportUtil.report("./report/Daily-Sales-Report.jrxml",
										params);
							}
						}
					} else if (selections[i].equals("Inventory Report")) {

						if (combo.getText().length() > 0) {
							String categoryName = combo.getText();
							Session session = HibernateUtil.getSessionFactory()
									.getCurrentSession();
							session.beginTransaction();

							java.util.List<Category> categories = session
									.createCriteria(CategoryModel.class).add(
											Expression.eq(Category.FLD_NAME,
													combo.getText()))
									.setMaxResults(1).list();
							if (categories != null && !categories.isEmpty()) {
								params.put("cat_id", categories.get(0).getId());
							}
						}

						ReportUtil.report("./report/Inventory.jrxml", params);
					} else if (selections[i].equals("Inventory Updates")) {
						if (combo.getText().length() > 0) {
							String categoryName = combo.getText();
							Session session = HibernateUtil.getSessionFactory()
									.getCurrentSession();
							session.beginTransaction();

							java.util.List<Category> categories = session
									.createCriteria(CategoryModel.class).add(
											Expression.eq(Category.FLD_NAME,
													combo.getText()))
									.setMaxResults(1).list();
							if (categories != null && !categories.isEmpty()) {
								params.put("cat_id", categories.get(0).getId());
							}
						}

						ReportUtil
								.report(
										"./report/Inventory-Balancesheet.jrxml",
										params);
					} else if (selections[i].equals("Inventory Stock Card")) {
						if (combo_2.getText().length() > 0) {
							String sku = combo_2.getText();
							
							if (sku.indexOf("[") != -1 && sku.indexOf("]") != -1) {
								sku = sku.substring(sku.indexOf("[") + 1, sku.indexOf("]"));
							}
							
							Session session = HibernateUtil.getSessionFactory()
									.getCurrentSession();
							session.beginTransaction();

							java.util.List<Product> products = session
									.createCriteria(ProductModel.class)
									.add(Expression.eq(Product.FLD_SKU, sku))
									.setMaxResults(1).list();

							if (products != null && !products.isEmpty()) {
								params.put("prod_id", products.get(0).getId());
							}
						}

						ReportUtil.report("./report/Inventory-StockCard.jrxml",
								params);
					} else if (selections[i].equals("Profit Report")) {

						ReportUtil.report("./report/Profit-Report.jrxml",
								params);
					} else if (selections[i].equals("Deleted Receipt Report")) {
						ReportUtil.report("./report/Deleted-Receipt-Report.jrxml",
								params);
					} else {
						ReportUtil
								.report(
										"./report/Daily-Worksheet-Report.jrxml",
										params);
					}
					break;
				}
			}
		} catch (Exception e) {
			log.error("Unable to display report.", e);
		}
	}

	private void doShowForm(List list, Combo combo, Combo combo_2,
			Combo combo_3, Label text, Label text_2, Label text_3) {
		if (list.getSelection() != null && list.getSelection().length > 0) {
			for (int i = 0; i < list.getSelection().length; i++) {
				String select = list.getSelection()[i];
				if (select.equals("Inventory Report")
						|| select.equals("Inventory Updates")) {
					combo.setVisible(true);
					combo_2.setVisible(false);
					combo_3.setVisible(false);
					text.setVisible(true);
					text_2.setVisible(false);
					text_3.setVisible(false);
					populateCombo(combo);
				} else if (select.equals("Inventory Stock Card")) {
					combo.setVisible(false);
					combo_2.setVisible(true);
					combo_3.setVisible(false);
					text.setVisible(false);
					text_2.setVisible(true);
					text_3.setVisible(false);
					populateCombo2(combo_2);
				} else if (select.equals("Sales Report")) {
					combo.setVisible(false);
					combo_2.setVisible(false);
					combo_3.setVisible(true);
					text.setVisible(false);
					text_2.setVisible(false);
					text_3.setVisible(true);
					populateCombo3(combo_3);
				} else {
					text.setVisible(false);
					text_2.setVisible(false);
					text_3.setVisible(false);
					combo.setVisible(false);
					combo_2.setVisible(false);
					combo_3.setVisible(false);
				}
			}
		}
	}

	private void populateCombo(Combo combo) {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();

		java.util.List<Category> categories = new ArrayList<Category>();
		categories = session.createCriteria(CategoryModel.class).add(
				Expression.eq(Category.FLD_STATUS, AppConstant.STATUS_ACTIVE))
				.list();

		combo.removeAll();

		if (categories != null && !categories.isEmpty()) {
			for (Iterator<Category> iter = categories.iterator(); iter
					.hasNext();) {
				Category category = iter.next();
				combo.add(category.getName());
			}
			combo.select(0);
		}

		combo.setVisible(true);
	}

	private void populateCombo2(Combo combo) {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();

		java.util.List<Product> products = session.createCriteria(
				ProductModel.class).add(
				Expression.eq(Product.FLD_STATUS, AppConstant.STATUS_ACTIVE))
				.addOrder(Order.asc(Product.FLD_NAME)).list();

		combo.removeAll();

		if (products != null && !products.isEmpty()) {
			for (Iterator<Product> iter = products.iterator(); iter.hasNext();) {
				Product product = iter.next();
				combo.add(product.getName() + " [" + product.getSku() + "]");
			}
			combo.select(0);
		}

		combo.setVisible(true);
	}

	private void populateCombo3(Combo combo) {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();

		java.util.List<Employee> employees = session.createCriteria(
				EmployeeModel.class).add(
				Expression.eq(Employee.FLD_STATUS, AppConstant.STATUS_ACTIVE))
				.addOrder(Order.asc(Employee.FLD_NAME))
				.list();
		
		combo.removeAll();
		combo.add("All Employees");
		if (employees != null && !employees.isEmpty()) {
			for (Iterator<Employee> iter = employees.iterator(); iter.hasNext();) {
				Employee employee = iter.next();
				combo.add(employee.getName());
			}
			combo.select(0);
		}
		
		combo.setVisible(true);
	}

	public Shell getShell() {
		return shell;
	}

	public Category getCategory() {
		return category;
	}

	public void setCategory(Object category) {
		if (category != null) {
			if (category instanceof Category) {
				this.category = (Category) category;
			}
		}
	}

}
